/**
 * 文件：BitmapManager.java
 * 包名：com.ronri.common;   --- 正式发布时需要修正
 * 说明：图片处理库
 * 作者：MS During
 * 日期：2017/4/27
 * 历史：
 */
package com.ronri.common;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.ExifInterface;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ImageView;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;


public class BitmapManager {

    /***
     * 获取网页上的图片
     * @param url
     * @return
     */
    public static Bitmap returnBitMap(String url){
        URL myFileUrl = null;
        Bitmap bitmap = null;
        try {
            myFileUrl = new URL(url);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        try {
            HttpURLConnection conn = (HttpURLConnection) myFileUrl
                    .openConnection();
            conn.setDoInput(true);
            conn.connect();
            InputStream is = conn.getInputStream();
            bitmap = BitmapFactory.decodeStream(is);
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;
    }

    /**
     * 根据图片路径进行压缩图片
     * @param srcPath
     * @return
     */
    public static Bitmap getimage(String srcPath, int size) {
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        //开始读入图片，此时把options.inJustDecodeBounds 设回true了,表示只返回宽高
        newOpts.inJustDecodeBounds = true;
        Bitmap bitmap = BitmapFactory.decodeFile(srcPath,newOpts);//此时返回bm为空

        newOpts.inJustDecodeBounds = false;
        //当前图片宽高
        float w = newOpts.outWidth;
        float h = newOpts.outHeight;
        //现在主流手机比较多是800*480分辨率，所以高和宽我们设置为
        float hh = 800f;//这里设置高度为800f
        float ww = 480f;//这里设置宽度为480f
        //缩放比。由于是固定比例缩放，只用高或者宽其中一个数据进行计算即可
        int be = 1;//be=1表示不缩放
        if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放
            Log.e("fileupload","------原始缩放比例 --------" + (newOpts.outWidth / ww));
            be = (int)(newOpts.outWidth / ww);
            //有时会出现be=3.2或5.2现象，如果不做处理压缩还会失败
            if ((newOpts.outWidth / ww) > be) {

                be += 1;
            }
            //be = Math.round((float) newOpts.outWidth / (float) ww);
        } else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放
            Log.e("fileupload","------原始缩放比例 --------" + (newOpts.outHeight / hh));
            be = (int)(newOpts.outHeight / hh);
            if ((newOpts.outHeight / hh) > be) {

                be += 1;
            }
            //be = Math.round((float) newOpts.outHeight / (float) hh);
        }
        if (be <= 0){

            be = 1;
        }
        newOpts.inSampleSize = be;//设置缩放比例
        Log.e("fileupload","------设置缩放比例 --------" + newOpts.inSampleSize);
        //重新读入图片，注意此时已经把options.inJustDecodeBounds 设回false了
        bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
        return compressImage(bitmap,size);//压缩好比例大小后再进行质量压缩
    }

    /**
     * 压缩图片
     * @param image
     * @param size
     * @return
     */
    private static Bitmap compressImage(Bitmap image, int size) {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
        int options = 100;

        while ((baos.toByteArray().length / 1024) >= size) {  //循环判断如果压缩后图片是否大于等于size,大于等于继续压缩
            Log.e("fileupload","------ByteArray--------" + baos.toByteArray().length / 1024);
            baos.reset();//重置baos即清空baos
            options -= 5;//每次都减少5
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%，把压缩后的数据存放到baos中
            Log.e("fileupload","------压缩质量--------" + options);
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片
        return bitmap;
    }

    /**
     * Bitmap转byte数组
     * @param bitmap
     * @return
     */
    public static byte[] compressBitmap(Bitmap bitmap) {
        if (bitmap == null ) {
            return null;//
        }
        /* 取得相片 */
        Bitmap tempBitmap = bitmap;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        tempBitmap.compress(Bitmap.CompressFormat.JPEG, 70, baos);// 如果签名是png的话，则不管quality是多少，都不会进行质量的压缩
        byte[] byteData = baos.toByteArray();
        return byteData;
    }

    /***
     * 旋转图片
     * @param angle
     * @param bitmap
     * @return
     */
    public static Bitmap rotaingImageView(int angle , Bitmap bitmap) {
        //旋转图片 动作
        Matrix matrix = new Matrix();;
        matrix.postRotate(angle);
        System.out.println("angle2=" + angle);

        // 创建新的图片
        Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
                bitmap.getWidth(), bitmap.getHeight(), matrix, true);

        if (null != bitmap){
            bitmap.recycle();
        }

        return resizedBitmap;
    }

    /***
     * 获取缩率图
     * @param filePath
     * @param reqWidth
     * @param reqHeight
     * @return
     */
    public static Bitmap getSmallBitmap(String filePath, int reqWidth,
                                        int reqHeight) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth,
                reqHeight);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;

        return BitmapFactory.decodeFile(filePath, options);
    }

    /***
     * 计算样图大小
     * @param options
     * @param reqWidth
     * @param reqHeight
     * @return
     */
    public static int calculateInSampleSize(BitmapFactory.Options options,
                                            int reqWidth, int reqHeight) {

        final int height = options.outHeight;
        final int width = options.outWidth;

        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {
            final int heightRatio = Math.round((float) height
                    / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }

        return inSampleSize;
    }
    /**
     * 读取图片属性：旋转的角度
     * @param path 图片绝对路径
     * @return degree旋转的角度
     */
    public static int readPictureDegree(String path) {
        int degree  = 0;
        try {
            ExifInterface exifInterface = new ExifInterface(path);
            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return degree;
    }


    /**
     * 清理map中的bitmap;
     * @param imgCache ImageCacheMap
     * @param maxSize 允许添加的最大图片数量
     * @param freeSize 释放掉图片的数量;
     */
    public static void recycleMapCache(LinkedHashMap<String, Bitmap> imgCache, int maxSize, int freeSize){
        //超出最大容量时清理
        if (imgCache.values().size() > maxSize) {
            synchronized(imgCache){
                Iterator<String> it = imgCache.keySet().iterator();
                while( it.hasNext()&&(imgCache.keySet().size()>freeSize)){
                    Bitmap bmp=imgCache.get(it.next());
                    if(bmp!=null&&!bmp.isRecycled()) {
                        bmp.recycle();
                        bmp=null;
                    }
                    it.remove();
                }
            }
            System.gc();
        }
    }


    /**
     * 清理View中的ImagView被BitMap占用的内存;
     * @param mapViews 一个View的合集
     */
    public static void recycle(Map<View,int[]> mapViews){
        synchronized(mapViews){
            Iterator<View> it = mapViews.keySet().iterator();
            while(it.hasNext()){
                //获取布局
                View view=it.next();
                if(view==null) return;
                //获取要布局内要回收的ids;
                int [] recycleIds=mapViews.get(view);

                //如果是listView,先找到每个布局文件.重要提示:每个ImagView在布局文件的第一层;
                if ((view instanceof AbsListView)) {
                    recycleAbsList((AbsListView)view, recycleIds);
                }
                //如果是ImageView,直接回收;
                else if(view instanceof ImageView){
                    recycleImageView(view);
                }
                //如果是ViewGroup,重要提示:每个ImagView在ViewGroup的第二层;
                else if ((view instanceof ViewGroup)) {
                    recycleViewGroup((ViewGroup)view, recycleIds);
                }
            }
        }
        System.gc();
    }


    /**
     * 回收继承自AbsListView的类,如GridView,ListView等
     * @param absView
     * @param recycleIds 要清理的Id的集合;
     */
    public static void recycleAbsList(AbsListView absView, int[]recycleIds){
        if(absView==null) return;
        synchronized(absView){
            //回收当前显示的区域
            for (int index = absView.getFirstVisiblePosition(); index <= absView.getLastVisiblePosition(); index++) {
                //获取每一个显示区域的具体ItemView
                ViewGroup views = (ViewGroup) absView.getAdapter().getView(index, null, absView);
                for(int count=0;count<recycleIds.length;count++){
                    recycleImageView(views.findViewById(recycleIds[count]));
                }
            }
        }
    }


    /**
     * 回收继承自AbsListView的类,如GridView,ListView等
     * @param recycleIds 要清理的Id的集合;
     */
    public static void recycleViewGroup(ViewGroup layout, int[]recycleIds){
        if(layout==null) return;
        synchronized(layout){
            for (int i = 0; i < layout.getChildCount(); i++) {
                View subView = layout.getChildAt(i);
                if (subView instanceof ViewGroup) {
                    for(int count=0;count<recycleIds.length;count++){
                        recycleImageView(subView.findViewById(recycleIds[count]));
                    }
                } else {
                    if (subView instanceof ImageView) {
                        recycleImageView((ImageView)subView);
                    }
                }
            }
        }
    }


    /**
     * 回收ImageView占用的图像内存;
     * @param view
     */
    public static void recycleImageView(View view){
        if(view==null) return;
        if(view instanceof ImageView){
            Drawable drawable=((ImageView) view).getDrawable();
            if(drawable instanceof BitmapDrawable){
                Bitmap bmp = ((BitmapDrawable)drawable).getBitmap();
                if (bmp != null && !bmp.isRecycled()){
                    ((ImageView) view).setImageBitmap(null);
                    bmp.recycle();
                    bmp=null;
                }
            }
        }
    }
}
